package org.jpropelleralt.list;

import java.util.List;

import org.jpropelleralt.collection.CollectionDeltaType;

/**
 * A representation of a change to a {@link List}. This describes the
 * scope of the changes, either giving the exact changes or
 * possibly an overstatement of the changes (for example,
 * when multiple regions of the list change, the {@link ListDelta}
 * would have to represent this change as a larger single region
 * changing).
 * 
 * A {@link ListDelta} represents only a single _type_ of change - for example
 * an {@link CollectionDeltaType#INSERTION} OR a {@link CollectionDeltaType#DELETION}, 
 * but not a combination of the two. The
 * exception is that a {@link CollectionDeltaType#COMPLETE} change represents any change at all - 
 * it simply advises that the list may differ in any way from its old
 * state. 
 * 
 * For a less overstated representation of changes
 * a {@link List} of {@link ListDelta} instances can be used, this can represent multi-region,
 * multi-type changes by breaking the change down into multiple operations.
 * Due to the way {@link List}s are used, most changes caused by calling {@link List} methods
 * will in fact constitute a single {@link ListDelta}, the exceptions 
 * being {@link List#removeAll(java.util.Collection)} and 
 * {@link List#retainAll(java.util.Collection)}, which may well be best
 * represented as a {@link CollectionDeltaType#COMPLETE} change in any case.
 * 
 * Implementations MUST BE IMMUTABLE
 */
public interface ListDelta {

	/**
	 * @return i such that for all int j < i,
	 * get(j) will return the same value now as it would have
	 * before the change, assuming that j is in list now, and
	 * was in list before change. May return -1 for 
	 * {@link CollectionDeltaType#COMPLETE} change,
	 * indicating first changed index is not known
	 */
	public int getFirstChangedIndex();
	
	/**
	 * @return i such that for all int j > i,
	 * get(j) will return the same value now as it would have
	 * before the change, assuming that j is in list now, and
	 * was in list before change. May return -1 for 
	 * {@link CollectionDeltaType#COMPLETE} change,
	 * indicating last changed index is not known
	 */
	public int getLastChangedIndex();
	
	/**
	 * @return The size of the list before the change
	 * For a {@link CollectionDeltaType#COMPLETE} change 
	 * this may be -1 indicating no knowledge of
	 * old size
	 */
	public int getOldSize();
	
	/**
	 * @return The size of the list after the change, or -1 if not known
	 */
	public int getNewSize();
	
	/**
	 * @return The type of change
	 */
	public CollectionDeltaType getType();
	
	/**
	 * @return The size of the change:
	 * 	For {@link CollectionDeltaType#COMPLETE}, this will be 
	 * the change in size of the list, or
	 * 	may be -1 indicating no knowledge of the size of the change
	 * 	For {@link CollectionDeltaType#REPLACEMENT}, the 
	 * number of possibly altered elements
	 * (from firstChangedIndex to lastChangedIndex).
	 * 	For {@link CollectionDeltaType#INSERTION}, 
	 * the number of inserted elements
	 * 	For {@link CollectionDeltaType#DELETION},
	 *  the number of deleted elements
	 */
	public int getChangeSize();
	
}
